#include "cinchunk.h"

/**
 * CInChunk - constructor
 */
CInChunk::CInChunk() {
  init();
}
//---------------------------------------------------------------------------

/**
 * CInChunk - copy constructor
 * @param chunk
 */
CInChunk::CInChunk(const CInChunk &chunk) {
  this->copyFrom(chunk);
}
//---------------------------------------------------------------------------

/**
 * operator= - assignment (copy) of chunk
 * @param chunk
 */
CInChunk& CInChunk::operator = (const CInChunk &chunk) {
  this->copyFrom(chunk);
  return *this;
}
//---------------------------------------------------------------------------

/**
 * init - initialization
 */
void CInChunk::init() {
  bytesRead = 0;
  length = 0;
  id = 0;
}
//---------------------------------------------------------------------------

/**
 * loadFromStream - reads this chunk from data stream
 * @param fh
 * @return num of bytes read from input stream 'fh'
 */
unsigned int CInChunk::loadFromStream(istream &fh) {
  unsigned int fhBytesRead(0);
  *this = readChunk(fh, fhBytesRead);
  return fhBytesRead;
}
//---------------------------------------------------------------------------

/**
 * getBytesRead - returns num of bytes read from chunk
 * @return num of bytes read from chunk
 */
unsigned int CInChunk::getBytesRead() {
  return bytesRead;
}
//---------------------------------------------------------------------------

/**
 * readChunk - reads chunk from data stream
 * @param fh
 * @param fhBytesRead
 * @return chunk
 */
CInChunk CInChunk::readChunk(istream &fh, unsigned int &fhBytesRead) {
  
  // Create sub chunk and read its header
  CInChunk result;
  result.bytesRead += CBinary::readUShort(fh, result.id);
  result.bytesRead += CBinary::readUInt(fh, result.length);
  
  // Copy amount of data equal to sub chunk into its data stream
  char* tmpBuffer = new char[result.length - result.bytesRead];
  fh.read(tmpBuffer, result.length - result.bytesRead);
  result.data.write(tmpBuffer, fh.gcount());
  delete [] tmpBuffer;
  
  fhBytesRead += result.bytesRead + fh.gcount();
  return result;
}
//---------------------------------------------------------------------------

/**
 * readChunk - reads sub chunk from data of chunk
 * @return chunk
 */
CInChunk CInChunk::readChunk() {
  return readChunk(data, bytesRead);
}
//---------------------------------------------------------------------------

/**
 * readCColor - Reads CColor from chunk
 * @return color
 */
CColor CInChunk::readCColor() {
  CColor color;
  bytesRead += CBinary::readCColor(data, color);
  return color;
}
//---------------------------------------------------------------------------

/**
 * readString - Reads string from chunk
 * @return string
 */
string CInChunk::readString() {
  string str;
  bytesRead += CBinary::readString(data, str);
  return str;
}
//---------------------------------------------------------------------------

/**
 * readPChar - reads strinf from PChar in chunk
 * @return string
 */
string CInChunk::readPChar() {
  string str;
  bytesRead += CBinary::readPChar(data, str);
  return str;
}
//---------------------------------------------------------------------------

/**
 * readBool - reads boolean from chunk
 * @return true/false
 */
bool CInChunk::readBool() {
  bool val;
  bytesRead += CBinary::readBool(data, val);
  return val;
}
//---------------------------------------------------------------------------

/**
 * readDouble - reads double from chunk
 * @return number
 */
double CInChunk::readDouble() {
  double num;
  bytesRead += CBinary::readDouble(data, num);
  return num;
}
//---------------------------------------------------------------------------

/**
 * readFloat - reads float from chunk
 * @return number
 */
float CInChunk::readFloat() {
  float num;
  bytesRead += CBinary::readFloat(data, num);
  return num;
}
//---------------------------------------------------------------------------

/**
 * readShort - reads short integer from chunk
 * @return number
 */
short CInChunk::readShort() {
  short num;
  bytesRead += CBinary::readShort(data, num);
  return num;
}
//---------------------------------------------------------------------------

/**
 * readChar - reads char from chunk
 * @return number
 */
char CInChunk::readChar() {
  char num;
  bytesRead += CBinary::readChar(data, num);
  return num;
}
//---------------------------------------------------------------------------

/**
 * readInt - reads integer from chunk
 * @return number
 */
int CInChunk::readInt() {
  int num;
  bytesRead += CBinary::readInt(data, num);
  return num;
}
//---------------------------------------------------------------------------

/**
 * readUShort - reads unsigned short integer from chunk
 * @return number
 */
unsigned short CInChunk::readUShort() {
  unsigned short num;
  bytesRead += CBinary::readUShort(data, num);
  return num;
}
//---------------------------------------------------------------------------

/**
 * readUChar - reads unsigned char from chunk
 * @return number
 */
unsigned char CInChunk::readUChar() {
  unsigned char num;
  bytesRead += CBinary::readUChar(data, num);
  return num;
}
//---------------------------------------------------------------------------

/**
 * readUInt - reads unsigned integer from chunk
 * @return number
 */
unsigned int CInChunk::readUInt() {
  unsigned int num;
  bytesRead += CBinary::readUInt(data, num);
  return num;
}
//---------------------------------------------------------------------------

/**
 * readBuffer - reads buffer of given size from chunk
 * @param buf
 * @param bufSize
 */
void CInChunk::readBuffer(char* buf, unsigned int bufSize) {
  CBinary::readBuffer(data, buf, bufSize);
}
//---------------------------------------------------------------------------

/**
 * copyFrom - copies chunk from another one
 * @param chunk
 */
void CInChunk::copyFrom(const CInChunk &chunk) {
  CBinaryChunk::copyFrom(chunk);
  bytesRead = chunk.bytesRead;
}
//---------------------------------------------------------------------------
